package controller

import (
	"bytes"
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/minio/minio-go/v7"
	"gominio/config"
	"gominio/domain"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
)

type FileController struct {
	Gominio *minio.Client
	Conf    *config.Config
}

func (c FileController) List(g *gin.Context) {
	objectsCh := c.Gominio.ListObjects(g, c.Conf.MinIO.Bucket, minio.ListObjectsOptions{})

	var objects []string
	for object := range objectsCh {
		if object.Err != nil {
			g.JSON(http.StatusInternalServerError, domain.RespError(object.Err.Error()))
			return
		}
		objects = append(objects, object.Key)
	}
	g.JSON(http.StatusOK, objects)
}

func (c FileController) Download(g *gin.Context) {
	objName := g.Query("name")
	// 下载对象
	object, err := c.Gominio.GetObject(g, c.Conf.MinIO.Bucket, objName, minio.GetObjectOptions{})
	if err != nil {
		g.JSON(http.StatusInternalServerError, domain.RespError(err.Error()))
	}
	defer func(object *minio.Object) {
		err := object.Close()
		if err != nil {
			fmt.Printf("关闭minio错误%v\n", err)
		}
	}(object)

	// 将对象内容读取到内存中
	var buffer bytes.Buffer
	if _, err := io.Copy(&buffer, object); err != nil {
		g.JSON(http.StatusInternalServerError, domain.RespError(err.Error()))
		return
	}
	// 设置响应头
	g.Data(http.StatusOK, "application/octet-stream", buffer.Bytes())
}

func (c FileController) Delete(g *gin.Context) {
	picName := g.Query("name")
	// 检查存储桶是否已经存在。
	exists, err := c.Gominio.BucketExists(context.Background(), c.Conf.MinIO.Bucket)
	if err == nil && exists {
		log.Printf("存储桶 %s 已经存在\n", c.Conf.MinIO.Bucket)
	} else if err == nil && !exists {
		err = c.Gominio.MakeBucket(context.Background(), c.Conf.MinIO.Bucket, minio.MakeBucketOptions{})
		log.Printf("创建存储桶 %s 成功", c.Conf.MinIO.Bucket)
	} else {
		log.Printf("查询存储桶状态异常: %s", err)
		return
	}
	err = c.Gominio.RemoveObject(context.Background(), c.Conf.MinIO.Bucket, picName, minio.RemoveObjectOptions{})
	if err != nil {
		g.JSON(http.StatusOK, "删除失败！")
		return
	}
	g.JSON(http.StatusOK, "删除成功！")

}

func (c FileController) Upload(g *gin.Context) {
	form, _ := g.MultipartForm()
	files := form.File["documents"]
	if len(files) > 10 {
		g.JSON(http.StatusOK, map[string]string{
			"code": "0",
			"msg":  "上传文件过多",
		})
		return
	}
	var filenames []string
	for _, file := range files {
		// log.Println(file.Filename)
		if file.Size > 20480000 {
			g.JSON(http.StatusOK, map[string]string{
				"code": "0",
				"msg":  fmt.Sprintf("上传文件%s过大", file.Filename),
			})
			return
		}

		// 检查存储桶是否已经存在。
		exists, err := c.Gominio.BucketExists(context.Background(), c.Conf.MinIO.Bucket)
		if err == nil && exists {
			log.Printf("存储桶 %s 已经存在\n", c.Conf.MinIO.Bucket)
		} else if err == nil && !exists {
			err = c.Gominio.MakeBucket(context.Background(), c.Conf.MinIO.Bucket, minio.MakeBucketOptions{})
			log.Printf("创建存储桶 %s 成功\n", c.Conf.MinIO.Bucket)
		} else {
			log.Printf("查询存储桶状态异常: %s\n", err)
			return
		}
		open, err := file.Open()
		if err != nil {
			log.Printf("打开文件异常: %s", err)
			return
		}
		filename := fmt.Sprintf("%s.png", strings.ReplaceAll(uuid.NewString(), "-", ""))
		_, err = c.Gominio.PutObject(context.Background(), c.Conf.MinIO.Bucket, filename, open, file.Size, minio.PutObjectOptions{ContentType: "image/png"})
		if err != nil {
			g.JSON(http.StatusOK, "上传失败")
			return
		}

		filenames = append(filenames, filename)
	}
	g.Header("files", strings.Join(filenames, ","))
	g.JSON(http.StatusOK, map[string]any{
		"code": "0",
		"msg":  "上传成功",
		"data": filenames,
	})
	return
}

// 单个任意文件上传
func (c FileController) UploadAny(g *gin.Context) {
	filename := g.GetHeader("filename")
	if len(filename) == 0 {
		g.JSON(http.StatusOK, map[string]string{
			"code": "0",
			"msg":  fmt.Sprintf("缺少文件名称"),
		})
	}
	// 获取文件大小
	sizeStr := g.GetHeader("size")
	size, _ := strconv.ParseInt(sizeStr, 10, 64)

	// 检查存储桶是否已经存在。
	exists, err := c.Gominio.BucketExists(context.Background(), c.Conf.MinIO.Bucket)
	if err == nil && exists {
		log.Printf("存储桶 %s 已经存在\n", c.Conf.MinIO.Bucket)
	} else if err == nil && !exists {
		err = c.Gominio.MakeBucket(context.Background(), c.Conf.MinIO.Bucket, minio.MakeBucketOptions{})
		log.Printf("创建存储桶 %s 成功\n", c.Conf.MinIO.Bucket)
	} else {
		log.Printf("查询存储桶状态异常: %s\n", err)
		return
	}

	_, err = c.Gominio.PutObject(context.Background(), c.Conf.MinIO.Bucket, filename, g.Request.Body, size, minio.PutObjectOptions{})

	if err != nil {
		fmt.Printf("%s", err.Error())
		g.JSON(http.StatusOK, "上传失败")
		return
	}

	g.JSON(http.StatusOK, map[string]any{
		"code": "0",
		"msg":  "上传成功",
		"data": filename,
	})
	return
}
